/*
 * A Mock OpenFMS Input driver.
 *
 * DLL file has four public functions: create, destroy, get_number_of_channels and captue.
 *   create - creates an instance representing a keyboard
 *   destroy - frees resources made ny the create function
 *   get_number_of_channels - retruns the number of channels used.
 *   catpure - reads ste state of the controller and retruns the captured data.
 *
 * Copyright (C) 2010 Johan Waldeback
 *  
 * This file is part of the OpenFMS project (http://www.openfms-project.org)
 * 
 * OpenFMS is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * \file MockInput_dll.cpp
 * \brief Mock input driver (Windows).
 *
 * Input driver with 16 mock channels. Each channel returns
 * a constant value, which can be calculated with the formua: 
 * sin(ch), where ch is the channel number (0-15). With the
 * following exception: Channels 4, 5, 6 and 7, which each ouputs a
 * time watying sine wave of frequency 1/(2*PI) Hz. The four channels
 * are 90 deg out of phase with each other.
 */

#include <stdint.h>
#include <math.h>
#include <windows.h>

extern "C" {

/**
 * Create an input device
 *
 * @return Handle to the created device, zero on fail.
 */
__declspec(dllexport) 
uint64_t create()
{
	// This mock input always succeeds.
	// Return anything except zero.
    return 1;
}

/**
 * Detroys an input device
 *
 * @param[in] _handle Handle to the input device.
 * @return Returns zero on success, non-zero on fail.
 */
__declspec(dllexport) 
uint32_t destroy(uint64_t _handle)
{
	// Mock input does not allocate any resources.
	// Just exit with success.
    return 0;
}
/**
 * Retrun the number of channels of the device.
 *
 * Mock input simulates 16, so this function will always return 16.
 *
 * @param[in] _handle Handle to the input device.
 * @return Returns the number of channels the device has.
 */
__declspec(dllexport) 
uint32_t get_number_of_channels(uint64_t _handle)
{
	//  Mock input simulates 16, so return 16.
	return 16;
}

/**
 * Capture and retrive channel data
 *
 * @param[in] _handle Handle to the input device to capture from
 * @param[out] _target Pointer to array of float to receive the data
 * @param[in] _start Index of first channel to capture
 * @param[in] _length Number of channels to receive
 * @return 0 on success, otherwise non-zero
 */
__declspec(dllexport) 
uint32_t capture(uint64_t _handle, float *_target, uint32_t _start, uint32_t _length)
{
	// capture clock.
	DWORD ticks = GetTickCount();

	// fill in result array according to rules described at the top of this file.
	size_t index = 0;
	for( uint32_t i =_start; i<(_start+_length); ++i, ++index ) {
		if( i== 4 ) {
			_target[index] = sinf( static_cast<float>(ticks)/1000 );
		}
		else if( i== 5 ) {
			_target[index] = cosf( static_cast<float>(ticks)/1000 );
		}
		else if( i== 6 ) {
			_target[index] = -sinf( static_cast<float>(ticks)/1000 );
		}
		else if( i== 7 ) {
			_target[index] = -cosf( static_cast<float>(ticks)/1000 );
		}
		else _target[index] = sinf( static_cast<float>(i)*.1f );
	}
    return 0;
}

} // extern "C"
